/*
 * Description:  Net Utils in windows
 */
#include "net_utils.h"
#include <algorithm>
#include <cctype>
#include <WinSock2.h>
#include <iphlpapi.h>
#include <windows.h>
#include "log.h"
#include "text_utils.h"

#pragma comment(lib, "iphlpapi.lib")

namespace COMMON {
const std::string ETHERNET_INTERFACE_DESCRIPTION = "Red Hat VirtIO Ethernet Adapter";

bool NetUtils::GetEthernetAdapterName(std::string& ethernetAdapterName)
{
    std::vector<std::pair<std::string, std::string>> netAdapters;
    if (!GetNetAdapters(netAdapters)) {
        LOG_ERR("Failed to get net adapters.");
        return false;
    }

    for (const auto& netAdapter : netAdapters) {
        if (netAdapter.first == ETHERNET_INTERFACE_DESCRIPTION) {
            ethernetAdapterName = netAdapter.second;
            return true;
        }
    }
    LOG_ERR("Ethernet adapter does not exist.");
    return false;
}

bool NetUtils::GetNetAdapters(std::vector<std::pair<std::string, std::string>>& netAdapters)
{
    ULONG bufferSize = 0;
    PIP_ADAPTER_ADDRESSES pAddresses = nullptr;

    // 第一次调用，获取所需的缓冲区大小
    if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &bufferSize)
        == ERROR_BUFFER_OVERFLOW) {
        pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufferSize);
        if (pAddresses == nullptr) {
            LOG_ERR("Failed to malloc.");
            return false;
        }
    }

    // 第二次调用，获取适配器信息
    if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &bufferSize) != ERROR_SUCCESS) {
        LOG_ERR("Failed to get adapters addresses.");
        return false;
    }
    PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses;
    while (pCurrAddresses) {
        std::string description = TextUtils::PwcharToString(pCurrAddresses->Description);
        std::string adapterName = pCurrAddresses->AdapterName;
        std::transform(adapterName.begin(), adapterName.end(), adapterName.begin(),
                       [](unsigned char c) { return std::tolower(c); });
        netAdapters.push_back({description, adapterName});
        pCurrAddresses = pCurrAddresses->Next;
    }

    if (pAddresses) {
        free(pAddresses);
    }
    return true;
}

bool NetUtils::DnsIsNull(bool& dnsIsNull)
{
    std::string ethernetAdapterName;
    if (!GetEthernetAdapterName(ethernetAdapterName)) {
        LOG_ERR("Failed to get ethernet adapter name.");
        return false;
    }
    std::string regPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\" + ethernetAdapterName;
    HKEY hKey;
    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regPath.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
        LOG_ERR("Failed to open registry key.");
        return false;
    }
    DWORD dataType;
    DWORD dataSize = 0;
    if (RegQueryValueExA(hKey, "NameServer", nullptr, &dataType, nullptr, &dataSize) != ERROR_SUCCESS) {
        RegCloseKey(hKey);
        LOG_INFO("Query NameServer failed.");
        dnsIsNull = true; // 如果查询失败，视为空
        return true;
    }
    if ((dataType == REG_SZ || dataType == REG_EXPAND_SZ) && dataSize > 0) {
        std::vector<char> buffer(dataSize);
        if (RegQueryValueExA(hKey, "NameServer", nullptr, &dataType,
            reinterpret_cast<LPBYTE>(buffer.data()), &dataSize) == ERROR_SUCCESS) {
            if (buffer[0] == '\0') { // 检查是否为空字符串
                LOG_INFO("NameServer is empty.");
                RegCloseKey(hKey);
                dnsIsNull = true;
                return true;
            }
        }
    }
    RegCloseKey(hKey);
    LOG_INFO("NameServer is not null.");
    dnsIsNull = false; // 其他情况视为非空
    return true;
}
}